/*
 * @(#)LogInfoInterceptor.java
 * 2011-5-28 下午03:19:50
 *
 * Copyright (c) 2018-2028, HangZhou QiYun InfoTech Co.,Ltd. .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.qyxx.platform.sysmng.logmng.web;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.web.util.UrlUtils;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.qyxx.platform.common.utils.encode.JsonBinder;
import com.qyxx.platform.common.utils.spring.SpringContextHolder;
import com.qyxx.platform.common.utils.web.ServletUtils;
import com.qyxx.platform.common.utils.web.struts2.Struts2Utils;
import com.qyxx.platform.sysmng.accountmng.entity.Authority;
import com.qyxx.platform.sysmng.accountmng.entity.User;
import com.qyxx.platform.sysmng.accountmng.service.ResourceCacheService;
import com.qyxx.platform.sysmng.logmng.entity.Log;
import com.qyxx.platform.sysmng.utils.Constants;


/**
 *  日志拦截器
 *  @author gxj
 *  @version 1.0
 *  @since 1.6 2011-5-28 下午03:19:50
 */

public class LogInfoInterceptor extends MethodFilterInterceptor {

	private static final long serialVersionUID = -5745919953874134846L;
	
	private static final Logger logger = LoggerFactory.getLogger(LogInfoInterceptor.class);
	
	private static LogInfoThreadPool logInfoThreadPool = SpringContextHolder.getBean("logInfoThreadPool");
	
	private static JsonBinder jsonBinder = JsonBinder.getAlwaysMapper();
	
	private ResourceCacheService resourceCacheService = SpringContextHolder.getBean("resourceCacheService");
	
	private static final String BEGIN_SIGN = "{";
	private static final String END_SIGN = "}";
	private static final String SIGN = "\\";
	
	@Override
	protected String doIntercept(ActionInvocation invocation) throws Exception {
		HttpServletRequest request = Struts2Utils.getRequest();
		User user = (User)Struts2Utils.getSessionAttribute(Constants.USER_SESSION_ID);
		if(null != user) {
			String url = UrlUtils.buildRequestUrl(request);
			logger.info("日志拦截器拦截url为：" + url);
			Authority auth = resourceCacheService.getResourceByUrl(url);
			Log log = new Log();
			String operName = "";
			String operDesc = "";
			if(auth!=null) {
				//权限范围内的日志记录
				operName = auth.getResourceName();
				operDesc = auth.getLogRule();
			} else {
				operName = "未知操作";
				operDesc = "无";
			}
			//List<String> params = EncodeUtils.getCharsBetweenSign(operDesc, BEGIN_SIGN, END_SIGN);
			log.setOperationUrl(StringUtils.substring(url, 0, 500));
			log.setLoginName(user.getLoginName());
			log.setRealName(user.getNickname());
			log.setIp(ServletUtils.getIpAddr(request));
			log.setMachineName(request.getRemoteHost());
			String method = invocation.getProxy().getMethod();
			log.setOperationMethod(method);
			log.setOperationName(operName);
			log.setOperationDesc(operDesc);
			//添加组织名称
			log.setOrgName(user.getOrganizationName());
			log.setOperationTime(new Date());
			log.setRemark(request.getHeader("User-Agent"));
			invocation.addPreResultListener(new PreResultHandler(log));
		}
		//logger.info("日志拦截器拦截result1");
		String result = invocation.invoke();
		//logger.info("日志拦截器拦截result2为：" + result);
		return result;
	}
	
	private static class PreResultHandler implements PreResultListener {

		private Log log;
		
		public PreResultHandler(Log log) {
			this.log = log;
		}
		
		@Override
		public void beforeResult(ActionInvocation invocation,
				String resultCode) {
			HttpServletRequest request = Struts2Utils.getRequest();
			String operDesc = log.getOperationDesc();
			if("无".equals(operDesc)) {//未知操作，记录请求内容
				//过滤系统自身请求
				if(log.getOperationUrl().indexOf("gs-mng!queryAjaxResult") > 0 
						|| log.getOperationUrl().indexOf("gs-mng!queryResult") > 0
						|| log.getOperationUrl().indexOf("gs-mng!dataFilter") > 0
						|| log.getOperationUrl().indexOf("gs-mng!queryFilterResult") > 0) {
					return;
				}
				//记录请求体内容
				String reqContent = jsonBinder.toJson(request.getParameterMap());
				operDesc = StringUtils.substring(reqContent, 0, 1000);
				//保存业务ID
				Long id = (Long)invocation.getStack().findValue("id");
				if(id != null) {
					log.setOperationName(log.getOperationName() + "(ID为" + id + ")");
				}
			} else {
				String[] params = StringUtils.substringsBetween(operDesc, "{", "}");
				if(null!=params && params.length > 0) {
					for(String param : params) {
						//从request参数中获取
						String[] paramVal = request.getParameterValues(param);
						String pattern = SIGN + BEGIN_SIGN + param + SIGN + END_SIGN;
						if(null!=paramVal && paramVal.length > 0) {
							operDesc = operDesc.replaceAll(pattern, StringUtils.join(paramVal, ","));
						} else {
							//从action InvocationContext中获取变量值
							Object o = invocation.getStack().findValue(param);
							operDesc = operDesc.replaceAll(pattern, StringUtils.defaultIfEmpty(String.valueOf(o), ""));
						}
					}
				}
			}
			log.setOperationDesc(operDesc);
			logInfoThreadPool.addLog(log);
		}
		
	}

}
